<template>
  <div class="search">
    <n-card :bordered="false" class="mt-4 proCard">
      <n-grid :cols="1" responsive="screen" :x-gap="24" style="margin-left: 15px">
        <n-gi :span="1">
          <n-space>
            <n-button type="info" icon-placement="left" @click="addDict">
              添加字典
              <template #icon>
                <div class="flex items-center">
                  <n-icon size="14">
                    <MdAdd />
                  </n-icon>
                </div>
              </template>
            </n-button>
            <n-button type="error" ghost icon-placement="left" @click="deleteDict">
              删除字典
              <template #icon>
                <div class="flex items-center">
                  <n-icon size="14">
                    <IosTrash />
                  </n-icon>
                </div>
              </template>
            </n-button>
            <n-button type="default" icon-placement="left" @click="refreshDict" :loading="loading">
              刷新
              <template #icon>
                <div class="flex items-center">
                  <n-icon size="14">
                    <IosRefresh />
                  </n-icon>
                </div>
              </template>
            </n-button>
          </n-space>
        </n-gi>
      </n-grid>
      <n-grid :cols="4" responsive="screen" :x-gap="24" style="margin-left: 15px">
        <n-gi :span="1">
          <div style="margin-top: 5px">
            <n-input
              suffix="ios-search"
              v-model:value="searchText"
              placeholder="输入字典名称搜索"
              clearable
            />
            <div class="tree-bar" :style="{maxHeight: maxHeight,marginTop:'10px',overflow:'auto'}">
              <n-tree ref="tre"
                      :data="treeData"
                      :cascade="true"
                       checkable
                      :pattern="searchText"
                      :default-selected-keys="defaultSelectKeys"
                      @update:selected-keys="selectTree"
                      @update:checked-keys="checkedKeys"/>
              <n-spin size="large" fix v-if="treeLoading"></n-spin>
            </div>
          </div>
        </n-gi>
        <n-gi :span="3">
          <n-form
            :model="queryForm"
            ref="queryFormRef"
            label-placement="left"
            inline>
            <n-grid :x-gap="12"  :cols="4" responsive="screen" @keydown.enter.native="handleSearch">
              <n-gi>
                <n-form-item label="字典项" path="itemText">
                  <n-input placeholder="请输入字典项" v-model:value="queryForm.itemText" />
                </n-form-item>
              </n-gi>
              <n-gi>
                <n-form-item label="状态" path="status">
                  <n-select v-model:value="queryForm.status" :options="options" clearable />
                </n-form-item>
              </n-gi>
              <n-gi>
                <n-form-item style="margin-right: 0" class="br">
                  <n-space>
                    <n-button type="primary" @click="handleSearch">
                      <template #icon>
                        <n-icon>
                          <IosSearch/>
                        </n-icon>
                      </template>查询</n-button>
                    <n-button @click="handleReset">
                      重置</n-button>
                  </n-space>
                </n-form-item>
              </n-gi>
            </n-grid>
          </n-form>
          <n-grid :x-gap="12" :cols="2" class="operation" style="margin-bottom: 1vh">
            <n-gi>
              <n-space>
                <n-button type="primary" @click="handleAdd">
                  <template #icon>
                    <n-icon>
                      <IosAdd/>
                    </n-icon>
                  </template>添加</n-button>
                <n-button type="error" @click="deleteAll">
                  <template #icon>
                    <n-icon>
                      <IosTrash/>
                    </n-icon>
                  </template>
                  删除</n-button>
              </n-space>
            </n-gi>
          </n-grid>
          <n-grid :cols="1" style="margin-bottom: 1vh;">
            <n-gi :span="1">
              <n-alert type="info" size="small">
                已选择
                <span class="select-count">{{selectedKeys.length}}</span> 项
                <a class="select-clear" @click="clearSelect" v-if="selectedKeys.length>0">清空</a>
              </n-alert>
            </n-gi>
          </n-grid>
          <n-grid :cols="1">
            <n-gi>
              <n-data-table
                ref="table"
                :columns="column"
                :pagination="pagination"
                :loading="loading"
                :remote="true"
                :data="data"
                :row-key="row => row.id"
                @update:checked-row-keys="handleCheck"
                @update:page-size="changePageSize"
                @update:page="changePage"
                :checked-row-keys="selectedKeys"
              >
              </n-data-table>
            </n-gi>
          </n-grid>
        </n-gi>
      </n-grid>
    </n-card>
    <n-modal v-model:show="dictShowModal" :show-icon="false"  preset="dialog" title="新增字典" @update:show="closeDictForm">
      <n-form
        ref="dictFormRef"
        label-placement="left"
        :model="dictForm"
        :label-width="100"
        :rules="dictRules"
      >
        <n-form-item path="dictName" label="字典名称">
          <n-input
            v-model:value="dictForm.dictName"
            placeholder="请输入字典名称"
          >
          </n-input>
        </n-form-item>
        <n-form-item path="dictCode" label="字典编码">
          <n-input
            v-model:value="dictForm.dictCode"
            placeholder="请输入字典编码"
          >
          </n-input>
        </n-form-item>
        <n-form-item path="sort" label="排序">
          <n-input-number v-model:value="dictForm.sort" clearable :min="1"/>
        </n-form-item>
        <n-form-item label="字典描述" path="description">
          <n-input v-model:value="dictForm.description" type="textarea" placeholder="请输入字典描述" />
        </n-form-item>
      </n-form>
      <template #action>
        <n-space>
          <n-button @click="()=>(dictShowModal = false)">取消</n-button>
          <n-button type="info" @loading="submitLoading" @click="submitDictForm">确定</n-button>
        </n-space>
      </template>
    </n-modal>
    <n-modal v-model:show="dictItemShowModal" :show-icon="false"  preset="dialog" :title="modalTitle" @update:show="closeItemForm">
      <n-form
        ref="dictItemFormRef"
        label-placement="left"
        :model="dictItemForm"
        :label-width="100"
        :rules="dictItemRules"
      >
        <n-form-item path="itemText" label="字典标签">
          <n-input
            v-model:value="dictItemForm.itemText"
            placeholder="请输入字典标签"
          >
          </n-input>
        </n-form-item>
        <n-form-item path="itemValue" label="字典值">
          <n-input
            v-model:value="dictItemForm.itemValue"
            placeholder="请输入字典值"
          >
          </n-input>
        </n-form-item>
<!--        <n-form-item path="sort" label="排序">-->
<!--          <n-input-number v-model:value="dictForm.sort" clearable :min="1"/>-->
<!--        </n-form-item>-->
        <n-form-item path="status" label="状态">
          <n-switch v-model:value="dictItemForm.status" />
        </n-form-item>
        <n-form-item label="描述" path="description">
          <n-input v-model:value="dictItemForm.description" type="textarea" placeholder="请输入描述" />
        </n-form-item>
      </n-form>
      <template #action>
        <n-space>
          <n-button @click="closeItemForm">取消</n-button>
          <n-button type="info" @loading="itemLoading" @click="submitItemForm">确定</n-button>
        </n-space>
      </template>
    </n-modal>
  </div>
</template>

<script lang="ts">
import {defineComponent,h,ref,onMounted,reactive } from 'vue'
import {useMessage,NButton,NTag,useDialog } from 'naive-ui'
import {IosAdd,IosTrash, IosSearch,IosRefresh,MdAdd} from '@vicons/ionicons4'
import {
  loadDictData,
  findDictItemList,
  checkDictCode,
  saveDict,
  removeDict,
  deleteDictItem,
  addDictItem,
  editDictItem
} from "@/api/system/dict";
export default defineComponent({
  components:{
    IosSearch,
    IosAdd,
    IosTrash,
    IosRefresh,
    MdAdd,
    NTag
  },
  name: "dict",
  setup(){
    const message=useMessage();
    const dialog=useDialog();
    const searchText=ref('');
    const treeData=ref([]);
    const maxHeight=ref("500px");
    const treeLoading=ref(false);
    const loading=ref(false);
    const data=ref([]);
    const modalTitle=ref('');
    const treeCheckedKeys=ref([]);
    const dictShowModal=ref(false);
    const dictItemShowModal=ref(false);
    const submitLoading=ref(false);
    const defaultSelectKeys:any=ref([]);
    const initDictForm=()=>{
      return {
        dictName:'',
        dictCode:'',
        sort:1,
        description:''
      }
    }
    let dictForm=reactive(initDictForm());
    const initItemForm=()=>{
      return {
        itemText:'',
        itemValue:'',
        status:true,
        description:'',
        dictId:'',
        id:''
      }
    };
    const options=ref([
      {label:'启用',value:1},
      {label:'禁用',value:0}
    ])
    let dictItemForm=reactive(initItemForm());
    let dictItemFormRef=ref();
    const dictFormRef=ref();
    const dictRules={
      dictName:{required:true,message:'请输入字典名称',trigger:'blur'},
      dictCode:{required:true,trigger:'blur',
        validator: (rule, value) => {
          return new Promise((resolve, reject) => {
            if (value ==""||value==null) {
              reject(Error('请输入字典编码'))
            } else {
              checkDictCode({dictCode:value}).then(res => {
                if (res) {
                  reject(Error('字典编码已存在'))
                } else {
                  resolve()
                }
              })
            }
          })
        }
      },
      sort:{type:'number',required:true,message:'请输入排序值',trigger:['change','blur']}
    };
    const dictItemRules={
      itemText:{required:true,message:'请输入字典标签',trigger:['change','blur']},
      itemValue:{required:true,message:'请输入字典值',trigger:['change','blur']},
    }
    let initQueryForm=()=>{
      return  {
        page:1,
        pageSize:5,
        dictId:'',
        status:null,
      }
    }
    let queryForm=ref(initQueryForm());
    const queryFormRef=ref(null);
    const itemLoading=ref(false);
    const pagination=reactive({
      itemCount:null,
      prefix ({ itemCount }) {
        return `共 ${itemCount} 项`
      },
      page: 1,
      pageSize: 5,
      showSizePicker: true,
      pageSizes: [5,15,20,25,30],
    })
    const selectedKeys:any=ref([]);
    const column=ref([
      {
        type: "selection",
        width: 60,
        align: "center",
        fixed: "left"
      },
      {
        type: "index",
        width: 60,
        align: "center",
        fixed: "left"
      },
      {
        title:'字典项名称',
        key:'itemText',
        minWidth: 60,
        align: 'center',
        sortable: true,
      },
      {
        title: '字典名称',
        align: 'center',
        key: 'itemValue',
        minWidth: 120
      },
      {
        title: '创建时间',
        align: 'center',
        key: 'createTime',
        sortable: true,
        sortType: "desc",
        minWidth: 150
      },
      {
        title: "状态",
        key: "status",
        align: "center",
        width: 110,
        render: (row) => {
          if (row.status ==1) {
            return h("div", [
              h(NTag,
                {
                  type: 'success',
                },
                { default: () => '启用' }
              )
            ]);
          } else if (row.status==0) {
            return h("div", [
              h(NTag,
                {
                  type: 'error',
                },
                { default: () => '禁用' }
              )
            ]);
          }
        }
      },
      {
        title: '操作',
        key: 'actions',
        align:'center',
        render: function (row) {
          return h("div", [
            h(
              NButton,
              {
                type: "primary",
                size: "small",
                style: {
                  marginRight: "5px"
                },
                onClick: () => handleEdit(row)
              },
              {default: () => '编辑'}
            ),
            h(
              NButton,
              {
                type: "error",
                size: "small",
                onClick: () => handleDelete(row)
              },
              {default: () => '删除'}
            )
          ]);
        }
      }
    ])

    function handleDelete(row){
      selectedKeys.value=[];
      selectedKeys.value.push(row.id);
      deleteAll();
    }
    function handleReset() {
      Object.keys(queryForm.value).forEach((key) => {
        queryForm.value[key] = initQueryForm()[key] || null;
      });
      initDictItemList();
    }
    function submitItemForm() {
      dictItemFormRef.value.validate((error:Boolean)=>{
        if(!error){
           itemLoading.value=true;
           let obj;
           if(dictItemForm.id!=''){
             obj=editDictItem(dictItemForm)
           }else{
             obj=addDictItem(dictItemForm)
           }
           obj.then(res=>{
             if(res){
               message.success('操作成功');
               initDictItemList();
               closeItemForm();
             }
           })
        }
      })
    }
    function closeItemForm() {
      Object.keys(dictItemForm).forEach((key)=>{
        if(key!=='dictId'){
          dictItemForm[key]=null;
        }
      })
      itemLoading.value=false;
      dictItemShowModal.value=false;
    }
    function closeDictForm() {
      Object.keys(dictForm).forEach((key)=>{
        dictForm[key]=null;
      })
      submitLoading.value=false;
      dictShowModal.value=false;
    }
    function deleteAll() {
      if(selectedKeys.value.length<=0){
        message.warning('请选择您要删除的数据');
        return;
      }
      dialog.warning({
        title: '警告',
        content: '你确定要删除所选的'+selectedKeys.value.length+'条数据吗?删除后无法恢复',
        positiveText: '确定',
        negativeText: '取消',
        onPositiveClick:()=>{
          const ids = selectedKeys.value.join(",");
          deleteDictItem({ids:ids}).then(res=>{
            if(res){
               message.success('删除成功');
               initDictItemList();
            }
          })
        },
        onNegativeClick: () => {
        }
      })
    }
    function handleEdit(row) {
      modalTitle.value='编辑【'+(row as any).dictName+'】的字典值';
      dictItemForm=Object.assign(dictItemForm,row);
      defaultSelectKeys.value.push(row.dictId);
      dictItemShowModal.value=true;
    }
    function handleAdd() {
      if(dictItemForm.dictId==null||dictItemForm.dictId==''){
         message.warning('请先选择要添加的字典');
         return;
      }
      let dict = treeData.value.find((data:any)=>data.key===dictItemForm.dictId)
      modalTitle.value='添加【'+(dict as any).label+'】的字典值';
      dictItemShowModal.value=true;
    }
    const refreshDict=()=>{
      treeCheckedKeys.value=[]
      initDictTreeData();
    };
    const addDict=()=>{
      dictShowModal.value=true;
    };
    const deleteDict=()=>{
      if(treeCheckedKeys.value.length<=0){
        message.warning('请选择您要删除的数据');
        return;
      }
      dialog.warning({
        title: '警告',
        content: '你确定要删除所选的'+treeCheckedKeys.value.length+'条数据吗?删除后无法恢复',
        positiveText: '确定',
        negativeText: '取消',
        onPositiveClick:()=>{
          const ids = treeCheckedKeys.value.join(",");
          removeDict({ids:ids}).then(res=>{
              if(res){
                 message.success('删除成功');
                 initDictTreeData();
              }
          })
        },
        onNegativeClick: () => {
        }
      })
    }
    const submitDictForm=()=>{
      dictFormRef.value.validate((errors)=>{
        if(!errors){
          submitLoading.value=true;
           saveDict(dictForm).then(res=>{
             if(res){
               message.success('操作成功');
               initDictTreeData();

               closeDictForm();
             }
           })
        }
      })
    }
    function clearSelect() {
      selectedKeys.value=[];
    }
    function selectTree(keys){
      if(keys.length>0){
        queryForm.value.dictId=keys[0];
        dictItemForm.dictId=keys[0];
        initDictItemList();
      }
    }
    function checkedKeys(keys) {
      treeCheckedKeys.value=keys;
    }
    function changePageSize(value) {
      queryForm.value.pageSize=value;
      pagination.pageSize=value;
      initDictItemList();
    }
    function changePage(value) {
      queryForm.value.page=value;
      pagination.page=value;
      initDictItemList();
    }
    function handleCheck(keys) {
      selectedKeys.value=keys;
    }
    async function initDictItemList(){
      loading.value=true;
      await findDictItemList(queryForm.value).then(res=>{
        data.value=res.records;
        pagination.itemCount=res.total;
        loading.value=false;
      })
    }
    async function initDictTreeData(){
      treeLoading.value=true;
      await loadDictData().then(res=>{
        treeData.value=res;
        treeLoading.value=false;
      })
    }
    function handleSearch(){
      initDictItemList();
    }
    onMounted(() => {
       initDictTreeData();
       initDictItemList();
    })
    return {
      searchText,
      treeData,
      maxHeight,
      treeLoading,
      loading,
      data,
      column,
      pagination,
      queryForm,
      queryFormRef,
      modalTitle,
      submitDictForm,
      dictRules,
      selectedKeys,
      dictForm,
      dictFormRef,
      dictShowModal,
      submitLoading,
      dictItemForm,
      dictItemFormRef,
      dictItemShowModal,
      dictItemRules,
      defaultSelectKeys,
      options,
      refreshDict,
      addDict,
      deleteDict,
      selectTree,
      changePageSize,
      changePage,
      handleCheck,
      handleSearch,
      deleteAll,
      handleReset,
      handleAdd,
      clearSelect,
      checkedKeys,
      submitItemForm,
      closeItemForm,
      closeDictForm,
      itemLoading
    }
  }
})
</script>

<style lang="less" scoped>
@import "../../../styles/Table.less";
</style>
